{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 简单线性回归（最小二乘法）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 0. 引入依赖"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 导入数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "points = np.genfromtxt('data.csv', delimiter=',')\n",
    "\n",
    "# 提取 points 中的两列数据， 分别为 x, y\n",
    "x = points[:, 0]\n",
    "y = points[:, 1]\n",
    "\n",
    "# 用 plt 画出散点图\n",
    "plt.scatter(x, y)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 定义损失函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 损失函数是系数的函数，另外还需要传入数据的 x,y\n",
    "def compute_cost(w, b, points):\n",
    "    total_cost = 0\n",
    "    M = len(points)\n",
    "\n",
    "    # 逐点计算平方损失误差，然后求平均数\n",
    "    for i in range(M):\n",
    "        x = points[i, 0]\n",
    "        y = points[i, 1]\n",
    "        total_cost += ( y - w * x - b ) ** 2\n",
    "  \n",
    "    return total_cost/M"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. 定义算法拟合函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先定义一个求均值的函数\n",
    "def average(data):\n",
    "    sum = 0\n",
    "    num = len(data)\n",
    "    for i in range(num):\n",
    "        sum += data[i]\n",
    "    return sum/num\n",
    "\n",
    "# 定义核心拟合函数\n",
    "def fit(points):\n",
    "    M = len(points)\n",
    "    x_bar = average(points[:, 0])\n",
    "    \n",
    "    sum_yx = 0\n",
    "    sum_x2 = 0\n",
    "    sum_delta = 0\n",
    "\n",
    "    for i in range(M):\n",
    "        x = points[i, 0]\n",
    "        y = points[i, 1]\n",
    "        sum_yx += y * ( x - x_bar)\n",
    "        sum_x2 += x ** 2\n",
    "    # 根据公式计算\n",
    "    w = sum_yx / ( sum_x2 - M * (x_bar ** 2) )\n",
    "    \n",
    "    for i in range(M):\n",
    "        x = points[i, 0]\n",
    "        y = points[i, 1]\n",
    "        sum_delta += (y - w * x)\n",
    "    b = sum_delta / M\n",
    "    \n",
    "    return w, b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'point' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-44-a6ed5187427d>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mw\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoints\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'w is: '\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mw\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'b is: '\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0mcost\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcompute_cost\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mw\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpoints\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-42-c3c98f82364f>\u001b[0m in \u001b[0;36mfit\u001b[0;34m(points)\u001b[0m\n\u001b[1;32m     10\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoints\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m     \u001b[0mM\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoints\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m     \u001b[0mx_bar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0maverage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoint\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m     \u001b[0msum_yx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'point' is not defined"
     ]
    }
   ],
   "source": [
    "w, b = fit(points)\n",
    "print('w is: ', w)\n",
    "print('b is: ', b)\n",
    "\n",
    "cost = compute_cost(w, b, points)\n",
    "\n",
    "print('cost is: ', cost)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
